﻿using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;
using System.Collections.Generic;
using System.Globalization;

namespace RecruitmentProcess
{
    public sealed partial class RecruitmentWorkflow : StateMachineWorkflowActivity
    {

        string projectName = "Sales";
        int totTask = 4;
        int currentTask = 0;

        bool isMgrReviewForRejectApproved = false;
        bool isTechTeamApproved = false;
        bool isHRApproved = false;
        bool isDirectorApproved = false;
        string taskDescription = string.Empty;

        public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();

        public Guid createTaskInitialClearanceTaskId = default(System.Guid);
        public SPWorkflowTaskProperties createTaskInitialClearanceTaskProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties onTaskChangedInitialClearanceBeforeProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties onTaskChangedInitialClearanceAfterProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();

        public Guid createTaskTechnicalClearanceTaskId = default(System.Guid);
        public SPWorkflowTaskProperties createTaskTechnicalClearanceTaskProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties onTaskChangedTechnicalClearanceAfterProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties onTaskChangedTechnicalClearanceBeforeProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();

        public Guid createTaskHRClearanceTaskId = default(System.Guid);
        public SPWorkflowTaskProperties createTaskHRClearanceTaskProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties onTaskChangedHRClearanceAfterProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties onTaskChangedHRClearanceBeforeProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();

        public Guid createTaskAcceptedTaskId = default(System.Guid);
        public SPWorkflowTaskProperties createTaskAcceptedTaskProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties onTaskChangedAcceptedAfterProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties onTaskChangedAcceptedBeforeProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();

        public Guid createTaskRejectedTaskId = default(System.Guid);
        public SPWorkflowTaskProperties createTaskRejectedTaskProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties onTaskChangedRejectedAfterProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties onTaskChangedRejectedBeforeProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        string listGuid = "A5898A44-68F4-4030-8C14-9E073AD77E92";
        string taskFields = @"Title,
                            ApprovalLevel,
                            OnReAssignGoBackTo,
                            Approver,
                            TaskType,
                            FormType,
                            AllowReSubmitInput,
                            Project,
                            DueDate";
        public RecruitmentWorkflow()
        {
            InitializeComponent();

        }
        DateTime taskDueDate = default(DateTime);

        #region Workflow Activated
        private void onWorkflowActivatedInitial_Invoked(object sender, ExternalDataEventArgs e)
        {
            currentWFLevel = 1;
            SPUtility.WorkflowHelper wfHlp = new SPUtility.WorkflowHelper();
            wfHlp.ProcessBatchInsert(this.workflowProperties.SiteUrl, listGuid, this.workflowProperties.TemplateName, taskFields,
                this.workflowProperties.ItemId, this.workflowProperties.List.Title, this.workflowProperties.ListUrl);
        }
        #endregion Workflow Activated

        #region Initial Clearance
        private void createTaskInitialClearance_MethodInvoking(object sender, EventArgs e)
        {
            try
            {



                //Create a new TaskId for the Task
                this.createTaskInitialClearanceTaskId = Guid.NewGuid();

                //TaskProperties field is used to configure the Task Details.
                this.createTaskInitialClearanceTaskProperties.Title = "Initial Clearance";
                //You can assign a Task to an user or to a group. Here we assign the task to HR-Group
                this.createTaskInitialClearanceTaskProperties.AssignedTo = "devsp\\u1";

                //Task Type corresponds to TaskURN specified in Elements.xml
                this.createTaskInitialClearanceTaskProperties.TaskType = 1;

                this.createTaskInitialClearanceTaskProperties.DueDate = DateTime.Today.AddDays(5.0);
            }
            catch (Exception ex)
            {
                //Logging is used so that we can debug the errors in the workflow.
                System.Diagnostics.EventLog.WriteEntry("Recruitment Workflow", ex.StackTrace, System.Diagnostics.EventLogEntryType.Error);
                LogToHistoryListActivity log = new LogToHistoryListActivity();
                log.HistoryDescription = ex.StackTrace;
            }
            finally
            {

                AddChildItem();
            }
        }

        private void onTaskChangedInitialClearance_Invoked(object sender, ExternalDataEventArgs e)
        {
            try
            {
                // this.onTaskChangedInitialClearanceAfterProperties = this.onTaskChangedInitialClearance.AfterProperties;
                // this.onTaskChangedInitialClearanceBeforeProperties = this.onTaskChangedInitialClearance.BeforeProperties;

                //Set the PercentComplete property to 1.0 (i.e. 100%) to indicate that the task has been completed.
                this.onTaskChangedInitialClearanceAfterProperties.PercentComplete = (float)1.0;

                //Get the value of Remarks Column (InfoPath Form) by using the ExtendedProperties property
                string remarks = this.onTaskChangedInitialClearanceBeforeProperties.ExtendedProperties["Comment"].ToString();

                SPListItem listItem = this.workflowProperties.Item;

                //Write the remarks value to the list item
                if (listItem != null && listItem.Fields.ContainsField("InitialRemarks"))
                {
                    listItem["InitialRemarks"] = remarks;
                }
                if (this.onTaskChangedInitialClearanceAfterProperties.PercentComplete == (float)1.0 &&
                    this.onTaskChangedInitialClearanceAfterProperties.ExtendedProperties["ApprovalStatus"].ToString().Contains("Accept"))
                {
                    this.TaskOutcomeStatus = "Approved";
                    this.taskDescription = "Approved...";
                }

            }
            catch (Exception ex)
            {
                System.Diagnostics.EventLog.WriteEntry("Recruitment Workflow", ex.StackTrace, System.Diagnostics.EventLogEntryType.Error);
                LogToHistoryListActivity log = new LogToHistoryListActivity();
                log.HistoryDescription = ex.StackTrace;
                //throw ex;
            }
            finally
            {


            }
        }

        private void InitialClearanceApprovalProcess(object sender, ConditionalEventArgs e)
        {
            try
            {
                if (this.onTaskChangedInitialClearanceAfterProperties.ExtendedProperties["ApprovalStatus"].ToString().Contains("Accept"))
                {
                    e.Result = true;
                }
                else
                {
                    e.Result = false;
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.EventLog.WriteEntry("Recruitment Workflow", ex.StackTrace, System.Diagnostics.EventLogEntryType.Error);
                LogToHistoryListActivity log = new LogToHistoryListActivity();
                log.HistoryDescription = ex.StackTrace;
            }
        }
        #endregion Initial Clearance

        #region Technical Clearance
        private void createTaskTechnicalClearance_MethodInvoking(object sender, EventArgs e)
        {
            try
            {
                //Create a new TaskId for the Task
                this.createTaskTechnicalClearanceTaskId = Guid.NewGuid();

                //TaskProperties field is used to configure the Task Details.
                this.createTaskTechnicalClearanceTaskProperties.Title = "Technical Clearance";

                //You can assign a Task to an user or to a group. Here we assign the task to HR-Group

                SPListItem listItem = this.workflowProperties.Item;

                this.createTaskTechnicalClearanceTaskProperties.AssignedTo = "devsp\\u2";
                //Write the remarks value to the list item
                if (listItem != null)
                {
                    //Check if TechnicalInterviewAssignedTo Field has a value, and Assign this Task to the value of this Field
                    if (listItem.Fields.ContainsField("TechnicalInterviewAssignedTo"))
                    {
                        //   this.createTaskTechnicalClearanceTaskProperties.AssignedTo = listItem["TechnicalInterviewAssignedTo"].ToString();
                    }

                    //To send InitialRemarks to the InfoPath Form, we add it to the ExtendedProperty of the TaskProperties
                    //ExtendedProperties is a hashtable (Key-Value pair). 
                    //The Key will be the name of field we have used in ItemMetaData.xml and Value will be the value of remarks
                    if (listItem.Fields.ContainsField("InitialRemarks"))
                    {
                        if (this.createTaskTechnicalClearanceTaskProperties.ExtendedProperties.ContainsKey("InitialComments"))
                        {
                            this.createTaskTechnicalClearanceTaskProperties.ExtendedProperties["InitialComments"] = listItem["InitialRemarks"].ToString();
                        }
                        else
                        {
                            this.createTaskTechnicalClearanceTaskProperties.ExtendedProperties.Add("InitialComments", listItem["InitialRemarks"].ToString());
                        }
                    }
                }

                //Task Type corresponds to TaskURN specified in Elements.xml
                this.createTaskTechnicalClearanceTaskProperties.TaskType = 1;

                this.createTaskTechnicalClearanceTaskProperties.DueDate = DateTime.Today.AddDays(2.0);
            }
            catch (Exception ex)
            {
                //Logging is used so that we can debug the errors in the workflow.
                System.Diagnostics.EventLog.WriteEntry("Recruitment Workflow", ex.StackTrace, System.Diagnostics.EventLogEntryType.Error);
                LogToHistoryListActivity log = new LogToHistoryListActivity();
                log.HistoryDescription = ex.StackTrace;
            }
        }

        #endregion Technical Clearance

        #region HR Clearance
        private void createTaskHRClearance_MethodInvoking(object sender, EventArgs e)
        {
            try
            {
                //Create a new TaskId for the Task
                this.createTaskHRClearanceTaskId = Guid.NewGuid();

                //TaskProperties field is used to configure the Task Details.
                this.createTaskHRClearanceTaskProperties.Title = "HR Clearance Task";
                //You can assign a Task to an user or to a group. Here we assign the task to HR-Group
                this.createTaskHRClearanceTaskProperties.AssignedTo = "HRGroup";

                //Task Type corresponds to TaskURN specified in Elements.xml
                this.createTaskHRClearanceTaskProperties.TaskType = 1;

                this.createTaskHRClearanceTaskProperties.DueDate = DateTime.Today.AddDays(5.0);
            }
            catch (Exception ex)
            {
                //Logging is used so that we can debug the errors in the workflow.
                System.Diagnostics.EventLog.WriteEntry("Recruitment Workflow", ex.StackTrace, System.Diagnostics.EventLogEntryType.Error);
                LogToHistoryListActivity log = new LogToHistoryListActivity();
                log.HistoryDescription = ex.StackTrace;
            }
        }


        private void HRClearanceApprovalProcess(object sender, ConditionalEventArgs e)
        {

        }
        #endregion HR Clearance

        #region Accepted
        private void createTaskAccepted_MethodInvoking(object sender, EventArgs e)
        {
            try
            {
                //Create a new TaskId for the Task
                this.DirectorAcceptanceTaskId = Guid.NewGuid();

                //TaskProperties field is used to configure the Task Details.
                this.createTaskAcceptedTaskProperties.Title = "Director Approval";
                //You can assign a Task to an user or to a group. Here we assign the task to HR-Group
                this.createTaskAcceptedTaskProperties.AssignedTo = "devsp\\u3";

                //Task Type corresponds to TaskURN specified in Elements.xml
                this.createTaskAcceptedTaskProperties.TaskType = 1;

                this.createTaskAcceptedTaskProperties.DueDate = DateTime.Today.AddDays(5.0);
            }
            catch (Exception ex)
            {
                //Logging is used so that we can debug the errors in the workflow.
                System.Diagnostics.EventLog.WriteEntry("Recruitment Workflow", ex.StackTrace, System.Diagnostics.EventLogEntryType.Error);
                LogToHistoryListActivity log = new LogToHistoryListActivity();
                log.HistoryDescription = ex.StackTrace;
            }
        }

        private void onTaskChangedAccepted_Invoked(object sender, ExternalDataEventArgs e)
        {
            if (this.onTaskChangedInitialClearanceAfterProperties.ExtendedProperties["ApprovalStatus"].ToString().Contains("Accept"))
            {
                this.isDirectorApproved = true;
                this.TaskOutcomeStatus = "Director Approved";
                this.taskDescription = "Selected";
            }
            else
            {
                this.isDirectorApproved = false;
                this.TaskOutcomeStatus = "Director Rejected";
                this.taskDescription = "Please drop it";
            }
        }
        #endregion Accepted

        #region THIS IS WORKING CODE
        private void createTaskRejected_MethodInvoking(object sender, EventArgs e)
        {
            try
            {
                this.currentTask++;
                //Create a new TaskId for the Task
                this.MgrReviewForRejectedTaskId = Guid.NewGuid();

                //TaskProperties field is used to configure the Task Details.
                this.createTaskRejectedTaskProperties.Title = currentLevelName;// "Manager Review for rejected";
                this.createTaskRejectedTaskProperties.AssignedTo = programManager;// "devsp\\u4";
                //You can assign a Task to an user or to a group. Here we assign the task to HR-Group

                SPListItem listItem = this.workflowProperties.Item;
                //Write the remarks value to the list item

                //Task Type corresponds to TaskURN specified in Elements.xml
                this.createTaskRejectedTaskProperties.TaskType = 1;

                this.createTaskRejectedTaskProperties.DueDate = taskDueDate;// DateTime.Today.AddDays(2.0);
                AddChildItem();

            }
            catch (Exception ex)
            {
                //Logging is used so that we can debug the errors in the workflow.
                System.Diagnostics.EventLog.WriteEntry("Recruitment Workflow", ex.StackTrace, System.Diagnostics.EventLogEntryType.Error);
                LogToHistoryListActivity log = new LogToHistoryListActivity();
                log.HistoryDescription = ex.StackTrace;
            }
            finally
            {
                this.logHistoryDescription = "Task Created for " + currentLevelName;
            }

        }

        private Guid taskUniqueID = default(Guid);
        private void onTaskChangedRejected_Invoked(object sender, ExternalDataEventArgs e)
        {
            taskUniqueID = Guid.Empty;
            if (this.onTaskChangedRejectedAfterProperties.ExtendedProperties.ContainsKey("TaskUniqueID"))
            {
                if (this.onTaskChangedRejectedAfterProperties.ExtendedProperties["TaskUniqueID"] != null)
                {
                    taskUniqueID = new Guid(this.onTaskChangedRejectedAfterProperties.ExtendedProperties["TaskUniqueID"].ToString());
                }
            }

            if (this.onTaskChangedRejectedAfterProperties.ExtendedProperties["ApprovalStatus"].ToString().Contains("Accept"))
            {
                this.isMgrReviewForRejectApproved = false;
                this.TaskOutcomeStatus = "Approved";
                this.taskDescription = "Do not consider";
                this.logHistoryDescription = "Approved " + currentLevelName;
                currentWFLevel++;
            }
            else
            {
                this.isMgrReviewForRejectApproved = true;
                this.TaskOutcomeStatus = "Rejected";
                this.taskDescription = "Please reconsider this condidate";
                this.logHistoryDescription = "Rejected " + currentLevelName;
                currentWFLevel = OnReAssignGoBackTo;
            }

        }
        #endregion

        public static DependencyProperty TaskOutcomeStatusProperty = DependencyProperty.Register("TaskOutcomeStatus", typeof(System.String), typeof(RecruitmentProcess.RecruitmentWorkflow));

        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        [BrowsableAttribute(true)]
        [CategoryAttribute("Misc")]
        public String TaskOutcomeStatus
        {
            get
            {
                return ((string)(base.GetValue(RecruitmentProcess.RecruitmentWorkflow.TaskOutcomeStatusProperty)));
            }
            set
            {
                base.SetValue(RecruitmentProcess.RecruitmentWorkflow.TaskOutcomeStatusProperty, value);
            }
        }

        public Guid AAAA = default(System.Guid);
        public static DependencyProperty ManagerReviewRejectedTaskIdProperty = DependencyProperty.Register("ManagerReviewRejectedTaskId", typeof(System.Guid), typeof(RecruitmentProcess.RecruitmentWorkflow));

        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        [BrowsableAttribute(true)]
        [CategoryAttribute("Misc")]
        public Guid ManagerReviewRejectedTaskId
        {
            get
            {
                return ((System.Guid)(base.GetValue(RecruitmentProcess.RecruitmentWorkflow.ManagerReviewRejectedTaskIdProperty)));
            }
            set
            {
                base.SetValue(RecruitmentProcess.RecruitmentWorkflow.ManagerReviewRejectedTaskIdProperty, value);
            }
        }

        public Guid MgrReviewForRejectedTaskId = default(System.Guid);
        public Guid DirectorAcceptanceTaskId = default(System.Guid);
        public String HRTaskOutcome = default(System.String);

        private void completeTask4_MethodInvoking(object sender, EventArgs e)
        {
            this.HRTaskOutcome = "HR Approval" + this.taskDescription;
        }

        public String directorTaskOutcome = default(System.String);

        private void completeTask1_MethodInvoking(object sender, EventArgs e)
        {
            DeleteChildItem();
        }


        private void DeleteChildItem()
        {
            SPUtility.ListActivity listAction = new SPUtility.ListActivity();
            int itmID = 0;
            Int32.TryParse(this.workflowProperties.Item["ChildID"].ToString(), out itmID);

            if (itmID > 0)
            {
                if (taskUniqueID == Guid.Empty)
                {


                    listAction.DeleteItem(this.workflowProperties.SiteUrl, "Condidates", itmID);
                }
                else
                {
                    listAction.DeleteItem(this.workflowProperties.SiteUrl, "Condidates", itmID, taskUniqueID);
                }
            }
        }


        private void AddChildItem()
        {
            SPUtility.ListActivity listAction = new SPUtility.ListActivity();
            Dictionary<string, string> dict = new Dictionary<string, string>();
            dict.Add("Title", this.workflowProperties.Item.Title + "--" + this.workflowProperties.Item.ID.ToString());
            dict.Add("Reviews", taskApprover);
            dict.Add("Employee", programManager);
            dict.Add("ApprovalType", taskType);
            dict.Add("ApprovalLevel", currentWFLevel.ToString());

            int itmID = listAction.AddItem(this.workflowProperties.SiteUrl, "TaskHandler", dict);
            if (itmID > 0)
            {
                this.workflowProperties.Item["ChildID"] = itmID;
                this.workflowProperties.Item.UpdateOverwriteVersion();
            }
        }

        private void TaskHandler_ValidateTask(object sender, EventArgs e)
        {

            using (SPSite site = new SPSite(this.workflowProperties.SiteUrl))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    SPList configList = web.Lists[new Guid(listGuid)];///["TaskApprovalConfig99999"];
                    var listItem = (from SPListItem itm in configList.Items
                                    where
                                    itm["WFItemID"] != null &&
                                    itm["ApprovalLevel"] != null &&
                                    itm["Project"] != null &&
                                    string.Format("{0}", itm["WFItemID"]) == this.workflowProperties.ItemId.ToString()
                                    &&
                                    string.Format("{0}", itm["ApprovalLevel"]) == currentWFLevel.ToString()
                                    &&
                                    string.Format("{0}",itm["Project"]).Contains(this.workflowProperties.TemplateName)
                                    select itm).
                                    FirstOrDefault();
                    if (listItem == null)
                    {
                        this.IsAllTaskCompleted = true;
                    }
                    else
                    {
                        this.IsAllTaskCompleted = false;
                        taskApprover = getusergroupname( listItem["Approvers"]);//.ToString();
                        currentLevelName = listItem["Title"].ToString();
                        Int32.TryParse(
                            string.Format("{0}", 
                            (listItem["On Rework Go Back To"] == null?string.Empty:
                            listItem["On Rework Go Back To"])), out OnReAssignGoBackTo);
                        taskType = listItem["Approval Type"].ToString();
                        //listItem["TaskType"].ToString();
                        taskDueDate = listItem["DueDate"] == null?System.DateTime.Now: (DateTime)listItem["DueDate"];
                        if (taskApprover.Contains(';'))
                        {
                            programManager = taskApprover.Split(';')[0];
                        }
                    }

                }
            }

            //SPList configList= this
        }


        private string getusergroupname(object userObject)
        {
            SPFieldUserValueCollection AssignedTo = (SPFieldUserValueCollection)userObject;
            string curLoginName=string.Empty;
            foreach (var item in AssignedTo)
            {
                curLoginName += item.User.LoginName + ";";
            }

            return curLoginName.TrimEnd(';');
        }

        public bool IsAllTaskCompleted = false;
        private string programManager = string.Empty;
        private string taskType = "";
        private int currentWFLevel = 0;
        private string taskApprover = string.Empty;
        private string currentLevelName = string.Empty;
        private int OnReAssignGoBackTo = 0;
        public String logHistoryDescription = default(System.String);

        private void completeTask3_MethodInvoking(object sender, EventArgs e)
        {
            DeleteChildItem();
            this.workflowProperties.Item["ChildID"] = string.Empty;
            this.workflowProperties.Item.Update();
        }
    }
}
